package com.rs.game.player.skills;

import com.rs.cache.loaders.ItemDefinitions;
import com.rs.game.Animation;
import com.rs.game.Entity;
import com.rs.game.Graphics;
import com.rs.game.Hit;
import com.rs.game.World;
import com.rs.game.WorldTile;
import com.rs.game.Hit.HitLook;
import com.rs.game.item.Item;
import com.rs.game.npc.NPC;
import com.rs.game.player.CombatDefinitions;
import com.rs.game.player.Player;
import com.rs.game.player.Skills;
import com.rs.game.player.content.Magic;
import com.rs.game.tasks.WorldTask;
import com.rs.game.tasks.WorldTasksManager;
import com.rs.utils.Utils;

public class NPCCombat extends NPCStats {

	private Entity target;
	private int max_hit; //temporary constant
	private int mage_hit_gfx; //temporary constant
	public NPCCombat(Entity target) {
		this.target = target;
	}
	
	@Override
	public boolean start(NPC npc) {
		npc.setNextFaceEntity(target);
		if(checkAll(npc)) {
			addAttackedByDelay(npc);
			return true;
		}
		return false;
	}
	@Override
	public boolean process(NPC npc) {
		return checkAll(npc);
	}
	
	@Override
	public int processWithDelay(NPC npc) {
		/*if(player.getFreezeDelay() >= System.currentTimeMillis())
			return 0;
		int isRanging = isRanging(player);
		int spellId = player.getCombatDefinitions().getSpellId();
		int maxDistance = isRanging != 0 || spellId > 0 ? 7 : 0;
		int distanceX = player.getX()-target.getX();
		int distanceY = player.getY()-target.getY();
		int size = target.getSize();
		if(player.hasWalkSteps())
			maxDistance += 1;
		if(distanceX > size+maxDistance || distanceX < -1-maxDistance || distanceY > size+maxDistance || distanceY < -1-maxDistance)
			return 0;
		if(spellId > 0) {
			boolean manualCast = spellId >= 256;
			return mageAttack(player, manualCast ? spellId-256 : spellId, !manualCast);
		}else {
			if(isRanging == 0)
				return meleeAttack(player);
			else if (isRanging == 1) {
				player.getPackets().sendGameMessage("This ammo is not very effective with this weapon.");
				return -1;
			}else if (isRanging == 3) {
				player.getPackets().sendGameMessage("You dont have any ammo in your backpack.");
				return -1;
			}else
				return rangeAttack(player);
		}*/
		return 0; // For now
	}
	private void addAttackedByDelay(Entity npc) {
		target.setAttackedBy(npc);
		target.setAttackedByDelay(System.currentTimeMillis()+8000); //8seconds
	}
	
	@Override
	public void stop(NPC npc) {
		npc.setNextFaceEntity(null);
	}
	
	private boolean checkAll(NPC npc) {
		/*if(npc.isDead() || npc.hasFinished() || target.isDead() || target.hasFinished())
			return false;
		int distanceX = npc.getX()-target.getX();
		int distanceY = npc.getY()-target.getY();
		int size = target.getSize();
		int maxDistance = 16;
		if(npc.getPlane() != target.getPlane() || distanceX > size+maxDistance || distanceX < -1-maxDistance || distanceY > size+maxDistance || distanceY < -1-maxDistance)
			return false;
		if(npc.getFreezeDelay() >= System.currentTimeMillis())
			return true;
		if(target instanceof Player) {
			Player p2 = (Player) target;
			
		if(!target.isAtMultiArea() || ! npc.isAtMultiArea()) {
			if(npc.getAttackedBy() != target && npc.getAttackedByDelay() > System.currentTimeMillis())
				return false;
			if(target.getAttackedBy() != player && target.getAttackedByDelay() > System.currentTimeMillis())
				return false;
		}
		int isRanging = isRanging(npc);
		maxDistance = isRanging != 0 || npc.getCombatDefinitions().getSpellId() > 0 ? 7 : 0;
		if(distanceX > size+maxDistance || distanceX < -1-maxDistance || distanceY > size+maxDistance || distanceY < -1-maxDistance) {
			if(!npc.hasWalkSteps())
				npc.addWalkStepsInteract(target.getX(), target.getY(), 2, size, true);
			return true;
		}else {
			npc.resetWalkSteps();
		}
		if(npc.getX() == target.getX() && npc.getY() == target.getY()) {
			if(!npc.addWalkSteps(target.getX()+1, target.getY(), 1))
				if(!npc.addWalkSteps(target.getX()-1, target.getY(), 1))
					if(!npc.addWalkSteps(target.getX(), target.getY()+1, 1))
						if(!npc.addWalkSteps(target.getX(), target.getY()-1, 1))
							return false;
		}*/
		return true;
	}
	private int rangeAttack(final NPC npc) {
		
		//final int weaponId = NPC.getId();
		//int attackStyle = player.getCombatDefinitions().getAttackStyle();
		int combatDelay = getRangeCombatDelay(npc.getId());
		/*if(player.getCombatDefinitions().isUsingSpecialAttack()) {
			int specAmt = getSpecialAmmount(weaponId);
			if(specAmt == 0) {
				 player.getPackets().sendGameMessage("This weapon has no special Attack, if you still see special bar please relogin.");
				 player.getCombatDefinitions().desecreaseSpecialAttack(0);
				 return combatDelay;
			}
		    if(player.getCombatDefinitions().getSpecialAttackPercentage() < specAmt) {
				 player.getPackets().sendGameMessage("You don't have enough power left.");
				 player.getCombatDefinitions().desecreaseSpecialAttack(0);
				 return combatDelay;
			}
		    player.getCombatDefinitions().desecreaseSpecialAttack(specAmt);
		    switch(weaponId) {
			case 859: //magic longbow
			case 861: //magic shortbow
			case 10284: //Magic composite bow
			case 18332: //Magic longbow (sighted)
				 player.setNextAnimation(new Animation(1074));
	    		 player.setNextGraphics(new Graphics(249, 0, 100));
	    		 World.sendProjectile(player, target, 249, 41, 16, 41, 35, 16, 0);
	    		 World.sendProjectile(player, target, 249, 41, 16, 35, 35, 21, 0);
	    		 delayHit(1, weaponId, attackStyle, getRangeHit(player, getRandomMaxHit(player, weaponId, attackStyle, true, true, 1.0, true)));
	    		 delayHit(2, weaponId, attackStyle, getRangeHit(player, getRandomMaxHit(player, weaponId, attackStyle, true, true, 1.0, true)));
	    		 dropAmmo(player, 2);
	    	break;
		    case 11235: //dark bows
		    case 15701:
		    case 15702:
		    case 15703:
		    case 15704:
		    	 int ammoId = player.getEquipment().getAmmoId();
	    		 player.setNextAnimation(new Animation(getWeaponAttackEmote(weaponId, attackStyle)));
	    		 player.setNextGraphics(new Graphics(getArrowThrowGfxId(weaponId, ammoId), 0, 100));
		    	 if(ammoId == 11212) {
		    		 int damage = getRandomMaxHit(player, weaponId, attackStyle, true, true, 1.5, true);
		    		 if(damage < 80)
		    			 damage = 80;
		    		 int damage2 = getRandomMaxHit(player, weaponId, attackStyle, true, true, 1.5, true);
		    		 if(damage2 < 80)
		    			 damage2 = 80;
		    		 World.sendProjectile(player, target, 1099, 41, 16, 41, 35, 16, 0);
		    		 World.sendProjectile(player, target, 1099, 41, 16, 35, 35, 21, 0);
		    		 delayHit(1, weaponId, attackStyle, getRangeHit(player, damage));
		    		 delayHit(2, weaponId, attackStyle, getRangeHit(player, damage2));
		    		 WorldTasksManager.schedule(new WorldTask() {
						@Override
						public void run() {
							target.setNextGraphics(new Graphics(1100, 0, 100));
						}
		    		 }, 2);
		    	 }else{
		    		 int damage = getRandomMaxHit(player, weaponId, attackStyle, true, true, 1.3, true);
		    		 if(damage < 50)
		    			 damage = 50;
		    		 int damage2 = getRandomMaxHit(player, weaponId, attackStyle, true, true, 1.3, true);
		    		 if(damage2 < 50)
		    			 damage2 = 50;
		    		 World.sendProjectile(player, target, 1101, 41, 16, 41, 35, 16, 0);
		    		 World.sendProjectile(player, target, 1101, 41, 16, 35, 35, 21, 0);
		    		 delayHit(1, weaponId, attackStyle, getRangeHit(player, damage));
		    		 delayHit(2, weaponId, attackStyle, getRangeHit(player, damage2));
		    	 }
		    	 dropAmmo(player, 2);

		    	 break;
		    case 14684: //zanik cbow
		    	player.setNextAnimation(new Animation(getWeaponAttackEmote(weaponId, attackStyle)));
		    	player.setNextGraphics(new Graphics(1714));
		    	World.sendProjectile(player, target, 2001, 41, 41, 41, 35, 0, 0);
		    	delayHit(2, weaponId, attackStyle, getRangeHit(player, getRandomMaxHit(player, weaponId, attackStyle, true, true, 1.0, true)+30+Utils.getRandom(120)));
		    	dropAmmo(player);
		   	break;
		    default:
		    player.getPackets().sendGameMessage("This weapon has no special Attack, if you still see special bar please relogin.");
			return combatDelay;
		    }
			return combatDelay;
		}else {
		    if(weaponId != -1) {
		    	String weaponName = ItemDefinitions.getItemDefinitions(weaponId).getName();
			     if(weaponName.contains("throwing axe") || weaponName.contains("knife") || weaponName.contains("dart") || weaponName.contains("javelin") || weaponName.contains("thrownaxe")) {
			    	 player.setNextGraphics(new Graphics(getKnifeThrowGfxId(weaponId), 0, 100));
			    	 World.sendProjectile(player, target, getKnifeThrowGfxId(weaponId), 41, 16, 60, 30, 16, 0);
			    	 delayHit(1, weaponId, attackStyle, getRangeHit(player, getRandomMaxHit(player, weaponId, attackStyle, true)));
			    	 dropAmmo(player, -1);
			     }else if(weaponName.contains("crossbow")) {
			    	 int damage = getRandomMaxHit(player, weaponId, attackStyle, true);
			    	 int ammoId = player.getEquipment().getAmmoId();
			    	 if(ammoId != -1 && Utils.getRandom(10) == 5) {
			    		 switch(ammoId) {
			    		 case 9237:
			    			 target.setNextGraphics(new Graphics(755));
			    			 if(target instanceof Player) {
			    				 Player p2 = (Player) target;
			    				 p2.stopAll();
			    			 }else {
			    				 @SuppressWarnings("unused")
								NPC n = (NPC) target;
			    				 //TODO stop attack
			    			 }
			    			 break;
			    		 case 9242:
			    			 max_hit = Short.MAX_VALUE;
			    			 damage = (int) (target.getHitpoints()*0.2);
			    			 target.setNextGraphics(new Graphics(754));
			    			 player.applyHit(new Hit(target, player.getHitpoints() > 20 ? (int) (player.getHitpoints() * 0.1) : 1, HitLook.Reflect_Hit));
			    			 break;
			    		 case 9244:
			    			 target.setNextGraphics(new Graphics(756));
			    			 damage += Utils.getRandom(hasAntiDragProtection() ? 100 : 250);
			    			 break;
			    		 case 9245:
			    			 target.setNextGraphics(new Graphics(753));
			    			 damage += Utils.getRandom(150);
			    			 player.heal((int) (player.getMaxHitpoints() * 0.25));
			    			 break;
			    		 }
			    	 }
			    	 delayHit(2, weaponId, attackStyle, getRangeHit(player, damage));
			    	 dropAmmo(player);
			     }else if (weaponId == 15241) {//handcannon
			    	 if(Utils.getRandom(player.getSkills().getLevel(Skills.FIREMAKING)) == 0) {
			    		 player.setNextGraphics(new Graphics(2140)); 
			    		 player.getEquipment().getItems().set(3, null);
			    		 player.getEquipment().refresh(3);
			    		 player.getAppearence().generateAppearenceData();
			    		 player.applyHit(new Hit(player, Utils.getRandom(150)+10, HitLook.Hit));
			    		 player.setNextAnimation(new Animation(12175));
			    		 return combatDelay;
			    	 }else {
			    		 player.setNextGraphics(new Graphics(2138)); 
			    		 World.sendProjectile(player, target, 2143, 18, 18, 60, 30, 0, 0);
			    		 delayHit(1, weaponId, attackStyle, getRangeHit(player, getRandomMaxHit(player, weaponId, attackStyle, true)));
			    		 dropAmmo(player, -2);
			    	 }
			     }else { //bow/default
			    	 final int ammoId = player.getEquipment().getAmmoId();
			    	 player.setNextGraphics(new Graphics(getArrowThrowGfxId(weaponId, ammoId), 0, 100));
			    	 World.sendProjectile(player, target, getArrowProjectileGfxId(weaponId, ammoId), 41, 16, 41, 35, 16, 0);
			    	 delayHit(1, weaponId, attackStyle, getRangeHit(player, getRandomMaxHit(player, weaponId, attackStyle, true)));
			    	 if(weaponId == 11235 || weaponId == 15701|| weaponId == 15702
			    			 || weaponId == 15703  || weaponId == 15704) { //dbows
			    		 World.sendProjectile(player, target, getArrowProjectileGfxId(weaponId, ammoId), 41, 16, 35, 35, 21, 0);
			    		 delayHit(2, weaponId, attackStyle, getRangeHit(player, getRandomMaxHit(player, weaponId, attackStyle, true)));
						 dropAmmo(player, 2);
			    	 }else
			    		 dropAmmo(player);
			     }
				player.setNextAnimation(new Animation(getWeaponAttackEmote(weaponId, attackStyle)));
		    }
		}*/
		return combatDelay;
	}
	
	private int getRangeCombatDelay(int npcID) {
		int delay = 0;
		
		switch(npcID) {

		default:
			delay = 6;
		break;
		}
		
		return delay;
	}
	
}
